<template>
  <div v-loading="loading" class="app-container">
    <div v-if="title || $slots.titleAction" class="ptitle">
      {{ title }}
      <div class="action">
        <slot name="titleAction" />
      </div>
    </div>
    <slot name="headerAction" />
    <c-form
      v-show="!hideSearch"
      v-bind="searchConfig"
      ref="refsForm"
      v-model="form"
      type="inline"
      :form-info="searchConfig.formConfig"
      :size="size"
      :hide-btn="!searchConfig.formConfig || searchConfig.hideBtn"
      @sub="subForm"
      @cancel="resetForm"
    >
      <template #formSlot>
        <slot name="formSlot" />
      </template>
    </c-form>
    <!-- 操作按钮组 -->
    <div class="actions-wrap">
      <ActionBar :actions="actions" :class="{ 'mb-4': actions?.length }">
        <template v-for="(index, name) in $slots" :key="index" #[name]>
          <slot :name="name" />
        </template>
      </ActionBar>
      <div
        class="action-right"
        :class="{
          'mb-4':
            tableConfig.warning ||
            searchConfig.senior ||
            $slots.actionSlot ||
            (hideForm && searchConfig.formConfig?.length > 1)
        }"
      >
        <template v-if="hideForm && searchConfig.formConfig?.length > 1">
          <el-button
            icon="Search"
            circle
            class="ml-3"
            title="搜索"
            @click="hideSearch = !hideSearch"
          />
          <el-button icon="Refresh" circle title="刷新" @click="reload()" />
        </template>
        <slot name="actionSlot" />
      </div>
    </div>
    <div v-if="$slots.tableSlot || tableConfig.cols" class="fit-table">
      <slot
        v-if="$slots.tableSlot"
        name="tableSlot"
        :data-list="dataList"
        :limit="queryParams.pageSize"
        :total="total"
        :warning-type="warningType"
        :page="queryParams.pageNum"
      />
      <el-table
        v-else
        ref="table"
        border
        :size="size"
        table-layout="fixed"
        :data="dataList"
        height="100%"
        width="100%"
        stripe
        :row-key="tableConfig.rowKey"
        @selection-change="selectionChange"
        @row-click="rowClick"
        @row-dblclick="rowDblclick"
        @row-contextmenu="rowContextmenu"
        v-on="$attrs"
      >
        <el-table-column
          v-if="tableConfig.isChecked"
          type="selection"
          align="center"
          width="40"
          fixed="left"
          :selectable="selectable"
        />
        <el-table-column
          v-if="tableConfig.radioCheck"
          width="55"
          align="center"
          label="#"
          fixed="left"
        >
          <template #default="scope">
            <el-radio
              v-model="tmpSelection"
              class="radio-no-text"
              :disabled="hasSelectedList(row)"
              :label="row[tableConfig.rowKey || 'id']"
              @click.stop
              @change="value => rowClick(row, value)"
            >
&nbsp;
            </el-radio>
          </template>
        </el-table-column>
        <el-table-column
          v-if="!tableConfig.hideIndex"
          label="序号"
          align="center"
          width="55"
          type="index"
          fixed="left"
        >
          <template #default="{ $index }">
            {{
              $index + queryParams.pageSize * (queryParams.pageNum - 1) + 1
            }}
          </template>
        </el-table-column>

        <el-table-column
          v-for="(v, i) in tableConfig.cols.filter(v => v)"
          :key="i"
          :label="v.label"
          :prop="v.prop"
          :show-overflow-tooltip="!v.showAll"
          :width="v.width || (!v.minWidth ? 150 : '')"
          :align="v.align"
          :min-width="v.minWidth"
          :fixed="v.fixed || (v.type == 'action' || v.actions || v.actionFun ? 'right' : false)"
        >
          <template #default="scope">
            <div
              v-if="v.renderFun"
              style="overflow: hidden; white-space: nowrap; text-overflow: ellipsis"
            >
              <exSlot :render-fun="v.renderFun" :obj-data="scope" />
            </div>
            <el-link
              v-else-if="v.type == 'text'"
              :underline="false"
              @click.stop="v.click(scope?.row)"
            >
              {{ scope?.row[v.prop] }}
            </el-link>

            <div v-else-if="v.actions || v.actionFun">
              <template v-for="(k, j) in v.actions || v.actionFun(scope)">
                <el-tooltip :content="k.title || k.label" placement="top">
                  <el-link
                    v-if="!k.disabled || (k.disabled && k.disabled(scope.row))"
                    :key="j"
                    v-hasPermi="k.permission || []"
                    :title="v.title"
                    :underline="false"
                    @click.stop="k.click(scope.row)"
                  >
                    <x-icon v-if="k.icon" :source-icon="k.icon" />{{ k.label }}
                  </el-link>
                </el-tooltip>
              </template>
            </div>
            <DictSelect
              v-else-if="v.type == 'dict'"
              v-model="scope.row[v.prop]"
              :dict-name="v.dictName"
              :dict-list="v.dictList"
              :type="v.dictType || 'text'"
            />
            <span v-else>
              {{ scope?.row[v.prop] }}
            </span>
          </template>
        </el-table-column>
        <slot name="tableColumn" />
      </el-table>
    </div>
    <pagination
      v-if="!tableConfig.hidePage && !tableConfig.noPage && total"
      v-model:page="queryParams.pageNum"
      v-model:limit="queryParams.pageSize"
      :total="total"
      :size="size"
      v-bind="pageConfig"
      @pagination="loadData()"
    />
    <div class="table-footer">
      <slot name="tableFooter" />
    </div>
  </div>
</template>
<script>
  import { defineComponent, h } from 'vue'
  //自定义渲染表格内容插槽
  let exSlot = defineComponent({
    name: 'CusRender',
    props: {
      objData: Object,
      renderFun: Function
    },
    render() {
      return this.renderFun(h, this.objData)
    }
  })
  export default {
    components: { exSlot },
    filters: {},
    props: {
      hideForm: {
        type: Boolean,
        default: false
      },
      size: {
        type: String
      },
      searchConfig: {
        type: Object,
        default: () => {
          return {}
        }
      },
      pageConfig: {
        type: Object,
        default: () => {
          return {}
        }
      },
      actions: {
        type: Array
      },
      tableConfig: {
        type: Object,
        default: () => {
          return {
            selected: [],
            rowKey: 'id',
            hidePage: false,
            isChecked: false
          }
        }
      },
      tableConfigSublevel: {
        type: Object,
        default: () => {
          return {
            selected: [],
            rowKey: 'id',
            hidePage: false,
            isChecked: false
          }
        }
      },
      title: {
        type: String,
        default: ''
      }
    },
    emits: ['rowClick', 'selectionChange', 'rowDblclick', 'rowContextmenu', 'reset', 'changeData'],
    data() {
      return {
        hideSearch: !!this.hideForm,
        tmpSelection: null,
        warningType: Number(this.tableConfig.warning) || 0,
        total: 0,
        dataList: [],
        loading: false,
        form: JSON.parse(JSON.stringify(this.searchConfig?.value || {})),
        queryParams: {
          pageNum: 1,
          pageSize: 20
        },
        tmpQuery: {}
      }
    },
    methods: {
      //表格行是否可选
      selectable(row) {
        if (!this.tableConfig.selected?.length) return true
        return this.tableConfig.selected
          .map(v => v[this.tableConfig.rowKey])
          .includes(row[this.tableConfig.rowKey])
      },
      //是否可单选，传入已选数组selected
      hasSelectedList(row) {
        if (!this.tableConfig.selected?.length) return false
        return this.tableConfig.selected
          .map(v => v[this.tableConfig.rowKey])
          .includes(row[this.tableConfig.rowKey])
      },
      subForm(form) {
        this.form = form
        this.loadData()
      },
      resetForm(form) {
        this.warningType = 1
        this.queryParams.pageNum = 1
        this.form = form
        this.loadData()
        this.$emit('reset')
      },
      loadData(cusParmas = null) {
        this.loading = true
        cusParmas && (this.tmpQuery = cusParmas)
        let params = { ...this.form, ...this.tmpQuery }
        if (!this.tableConfig.noPage) {
          params = Object.assign({}, params, this.queryParams)
        }
        if (this.tableConfig.warning) {
          params.warningFlag = this.warningType
        }
        this.searchConfig
          .loadData(params)
          .then(res => {
            let list = res.rows || res.data || []
            if (this.tableConfig.parseTable) {
              list = this.tableConfig.parseTable(list)
            }
            this.dataList = list
            this.total = res.total || res.rows?.length || res.data?.length || 0
            this.$emit('changeData', res.rows, this.queryParams)
          })
          .finally(() => {
            this.loading = false
          })
      },
      reload() {
        this.queryParams.pageNum = 1
        this.form = this.$refs.refsForm.getForm()
        this.loadData()
      },
      setFormParams(params = {}) {
        this.$refs.refsForm.setFormParams(params)
      },
      setFormItem(params = {}) {
        this.$refs.refsForm.setFormItem(params)
      },
      selectionChange(selections, row) {
        this.$emit('selectionChange', selections, row)
      },
      rowContextmenu(row) {
        this.$emit('rowContextmenu', row)
      },
      rowDblclick(row, column) {
        this.$emit('rowDblclick', row, column)
      },
      rowClick(row, column, event) {
        // console.log('tableclickrow', event.target?.localName)
        if (this.tableConfig.radioCheck) {
          this.tmpSelection = row[this.tableConfig.rowKey || 'id']
          this.$emit('selectionChange', [row])
        }
        if (this.tableConfig.isChecked) {
          this.$refs.table.toggleRowSelection(row)
        }
        this.$emit('rowClick', row, column)
      }
    }
  }
</script>
